
const canvas = document.getElementById('canvas');

const topCanvas = document.getElementById('topCanvas'); // hover显示的图层

const hidCanvas = document.createElement('canvas'); // 取色图层,存在内存即可，不用绘制

const ctx = canvas.getContext('2d');
const hidCtx = hidCanvas.getContext('2d');
const topCtx = topCanvas.getContext('2d');

let width = hidCtx.width = topCtx.width = ctx.width = topCanvas.width = canvas.width = hidCanvas.width = document.body.offsetWidth;
let height = hidCtx.height = topCtx.height = ctx.height = topCanvas.height = canvas.height = hidCanvas.height = document.body.offsetHeight;

let mapHash = new Map();

const FILL_COLOR = '#074b7f';
const STROKE_COLOR = '#1aa0d2';
const HOVER_FILL_COLOR = '#094260';
const HOVER_STROKE_COLOR = '#1c1ba8';

let lastSelectedItem = ''; // 最后一次所在的省，如果在同一个省移动，就不重复渲染

initMap();

async function initMap() {
  let fetchHanlder = await fetch('../china.json');
  let GeoJSON = await fetchHanlder.json();

  GeoJSON.features.forEach((feature) => {
    let { center, name, centroid } = feature.properties;
    let geometry = feature.geometry.coordinates;

    const randomColor = (() => {
      const rdColor = getRandomColor();
      return mapHash.get(rdColor) ? arguments.callee() : rdColor;
    })();

    mapHash.set(randomColor, {
      name,
      center,
      centroid: centroid ? GeoToPos(centroid) : undefined,
      geometry,
      randomColor
    });

    geometry.forEach((geo) => {
      geo[0].forEach((geoPoint, index) => {
        geo[0][index] = GeoToPos(geoPoint);
      });

      geo = geo[0];
      // FILL_COLOR
      drawGraph(ctx, hidCtx, geo, 1, randomColor, randomColor, true, STROKE_COLOR);  
    });

    if (centroid) {
      const centerGeo = GeoToPos(centroid);
      drawText(ctx, name, {
        x: centerGeo.x,
        y: centerGeo.y,
      }, '8px "微软雅黑"', true, '#000');
    }
  });
}

let preSelect = false;
// 或者topCanvas
document.addEventListener('mousemove', (e) => {
  const pointX = e.clientX,pointY = e.clientY;
  const hidColor = hidCtx.getImageData(pointX, pointY, 1, 1).data;
  const hexColor = rgbToHex(hidColor[0], hidColor[1], hidColor[2]);

  const geoInfo = mapHash.get(hexColor);

  if (!geoInfo) {
    // top绘制
    preSelect && drawMap();
    preSelect = false;
    return;
  }

  preSelect = true;

  drawMap(geoInfo);
}, false)

function drawMap(geoInfo) {
  if (geoInfo && lastSelectedItem === geoInfo.randomColor) {
    return;
  }
  clear(topCtx);
  if (geoInfo) {
    // console.log(geoInfo);
    geoInfo.geometry[0].forEach((geo) => {
      drawOneGraph(topCtx, geo, 1, HOVER_FILL_COLOR, true, HOVER_STROKE_COLOR);
    });

    if (geoInfo.centroid) {
      drawText(topCtx, geoInfo.name, {
        x: geoInfo.centroid.x,
        y: geoInfo.centroid.y,
      }, '20px "微软雅黑"', true, '#fff');
    }

    lastSelectedItem = geoInfo.randomColor;
  } else {
    lastSelectedItem = '';
  }
}

function drawGraph(ctx, hidCtx, points, lineWidth, lowColor, color, isFill, strokColor) {
  drawOneGraph(ctx, points, lineWidth, color, true, strokColor);
  drawOneGraph(hidCtx, points, 0, lowColor, true);
}

function drawOneGraph(ctx, points, lineWidth, color, isFill, strokeColor) {
  ctx.save(); // 用来保存Canvas的状态
  ctx.beginPath();

  if(isFill) {
    color ? (ctx.fillStyle = color) : (ctx.strokeColor = color);
  }
  ctx.lineWidth = lineWidth;
  ctx.lineJoin = 'round';
  strokeColor && (ctx.strokeColor = strokeColor);

  points.forEach((point, index) => {
    if (!index) ctx.moveTo(point.x, point.y); // 移动笔到位置
    else ctx.lineTo(point.x, point.y);
  });

  ctx.closePath();

  isFill && ctx.fill(); // fill填充，stoke绘制路径
  (!isFill && color || strokeColor) && ctx.stroke();
  ctx.restore(); // 恢复画布状态，用来恢复Canvas旋转、缩放等之后的状态，当和canvas.save( )一起使用时，恢复到canvas.save( )保存时的状态。
}

function drawText(ctx, text, point, font, isFill, color) {
  ctx.save();
  ctx.font = font;
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  color && (ctx.fillStyle = color);
  isFill ? ctx.fillText(text, point.x, point.y) : ctx.strokeText(text, point.x, point.y);
}

// 清除图层
function clear(context) {
  if (context) {
    context.clearRect(0, 0, context.width, context.height);//清空画布
    return;
  }
}









//随机生成16位的颜色值
function getRandomColor() {
  return '#' + (function (color) {
      return (color += '0123456789abcdef'[Math.floor(Math.random() * 16)])
          && (color.length == 6) ? color : arguments.callee(color);
  })('');
}


function componentToHex(c) {
  var hex = c.toString(16);
  return hex.length == 1 ? "0" + hex : hex;
}

function rgbToHex(r, g, b) {
  return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}

//转换坐标地图坐标
function GeoToPos(pos) {
  let longitude = pos[0];//计算之前的经度
  let latitude = pos[1];//计算之前的维度
  //最大最小经纬度
  let bounds = {
    xMax: 140,
    yMax: 53.5,
    xMin: 70.5,
    yMin: 10,
  };

  const xScale = width / (bounds.xMax - bounds.xMin);
  const yScale = height / (bounds.yMax - bounds.yMin);

  const scale = xScale < yScale ? xScale : yScale; // 取小，避免超出

  const xoffset = width / 2.0 - Math.abs(bounds.xMax - bounds.xMin) / 2 * scale;
  const yoffset = height / 2.0 - Math.abs(bounds.yMax - bounds.yMin) / 2 * scale;

  const point = {
    x: (longitude - bounds.xMin) * scale + xoffset,
    y: (bounds.yMax - latitude) * scale + yoffset,
  }

  return point;
}